package org.rqb.panel;

import org.rqb.config.MyConfig;
import org.rqb.panel.partPanel.RequestHeadPanel;
import org.rqb.panel.partPanel.RequestHeadRowPanel;
import org.rqb.utils.HttpUtil;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.*;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.*;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

import static org.rqb.Constant.M3U8_SAVE_DIR;

public class M3u8Panel extends JPanel implements ActionListener {

    private JTextField urlField;
    private JButton startButton;
    private JButton chooseDirButton;
    private JProgressBar progressBar;

    private JPanel headerListPanel; // 请求头列表容器
    private List<RequestHeadPanel> headerPanels = new ArrayList<>();


    private JTextArea logArea;
    private JLabel dirLabel;  // 显示当前保存目录
    private JFileChooser fileChooser;
    private File saveDirectory;
    private String regex  = "^(https?://.+\\.m3u8)(\\?.*)?$";
    private Properties config = MyConfig.getConfig();
    private String saveM3u8Dir;
    private JButton addHeaderButton;

    public M3u8Panel() {
        layoutInit();
        listenerInit();
    }

    private void listenerInit() {
        startButton.addActionListener(this);
        chooseDirButton.addActionListener(this);
    }

    private void layoutInit() {
        this.setLayout(new BorderLayout());
        saveM3u8Dir = config.getProperty(M3U8_SAVE_DIR);

        // 顶部：URL输入+按钮
        JPanel topPanel = new JPanel(new BorderLayout(5, 5));
        urlField = new JTextField();
        startButton = new JButton("开始下载");
        topPanel.add(new JLabel("M3U8地址: "), BorderLayout.WEST);
        topPanel.add(urlField, BorderLayout.CENTER);
        topPanel.add(startButton, BorderLayout.EAST);
        add(topPanel, BorderLayout.NORTH);

        //-------------------- 请求头区域 --------------------
        JPanel requestHeaderMainPanel = new JPanel(new BorderLayout());
        headerListPanel = new JPanel();
        headerListPanel.setLayout(new BoxLayout(headerListPanel, BoxLayout.Y_AXIS));

        // 默认添加一行
        addHeaderRow();

        // 添加按钮
        addHeaderButton = new JButton("添加请求头");
        addHeaderButton.addActionListener(this);

        requestHeaderMainPanel.add(new JScrollPane(headerListPanel), BorderLayout.CENTER);
        requestHeaderMainPanel.add(addHeaderButton, BorderLayout.SOUTH);

        //-------------------- 日志区域 --------------------
        logArea = new JTextArea();
        logArea.setEditable(false);
        JScrollPane logScrollPane = new JScrollPane(logArea);

        //-------------------- 中部整体合成 --------------------
        JSplitPane centerSplit = new JSplitPane(JSplitPane.VERTICAL_SPLIT, requestHeaderMainPanel, logScrollPane);
        centerSplit.setResizeWeight(0.3);  // 上面占 30%
        add(centerSplit, BorderLayout.CENTER);

        //-------------------- 底部区域 --------------------
        JPanel bottomPanel = new JPanel(new BorderLayout(5,5));

        progressBar = new JProgressBar(0, 100);
        bottomPanel.add(progressBar, BorderLayout.NORTH);

        JPanel dirPanel = new JPanel(new BorderLayout(5,5));
        chooseDirButton = new JButton("选择保存目录");
        dirLabel = new JLabel(saveM3u8Dir == null ? "请选择保存目录" : saveM3u8Dir);
        dirPanel.add(chooseDirButton, BorderLayout.WEST);
        dirPanel.add(dirLabel, BorderLayout.CENTER);

        bottomPanel.add(dirPanel, BorderLayout.SOUTH);
        add(bottomPanel, BorderLayout.SOUTH);

        //------------------- 文件选择器初始化 ------------------
        fileChooser = new JFileChooser();
        fileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
        fileChooser.setDialogTitle("选择保存目录");
    }

    //添加请求头
    private void addHeaderRow() {
        RequestHeadRowPanel rowPanel = new RequestHeadRowPanel();
        headerPanels.add(rowPanel.getLeftPanel());
        headerPanels.add(rowPanel.getRightPanel());
        headerListPanel.add(rowPanel);
        headerListPanel.revalidate();
        headerListPanel.repaint();
    }


    @Override
    public void actionPerformed(ActionEvent e) {
        if (e.getSource() == startButton) {
            startDownload();
        } else if (e.getSource() == chooseDirButton) {
            selectSaveDirectory();
        } else if (e.getSource() == addHeaderButton) {
            addHeaderRow();
        }
    }

    private void selectSaveDirectory() {
        int result = fileChooser.showOpenDialog(this);
        if (result == JFileChooser.APPROVE_OPTION) {
            saveDirectory = fileChooser.getSelectedFile();
            saveM3u8Dir = saveDirectory.getAbsolutePath();
            //更新配置文件
            HashMap<String, String> configMap = new HashMap<>();
            configMap.put(M3U8_SAVE_DIR, saveM3u8Dir);
            MyConfig.updateConfig(configMap);

            dirLabel.setText("保存目录: " + saveM3u8Dir);
            logArea.append("保存目录已设置为: " + saveM3u8Dir + "\n");
        }
    }

    //获取所有请求参数
    private HashMap<String, String> getAllRequestHeaders() {
        HashMap<String, String> headers = new HashMap<>();
        for (RequestHeadPanel panel : headerPanels) {
            String key = panel.getKey();
            String value = panel.getValue();
            if (!key.isEmpty() && !value.isEmpty()) {
                headers.put(key, value);
            }
        }
        return headers;
    }



    private void startDownload() {
        String m3u8Url = urlField.getText().trim();
        if (m3u8Url.isEmpty()) {
            JOptionPane.showMessageDialog(this, "请输入M3U8地址！");
            return;
        }

        if (!m3u8Url.matches(regex)) {
            JOptionPane.showMessageDialog(this, "url地址输入错误！");
            return;
        }

        if (saveM3u8Dir.isEmpty()) {
            JOptionPane.showMessageDialog(this, "请先选择保存目录！");
            return;
        }

        startButton.setEnabled(false);
        logArea.append("准备开始下载: " + m3u8Url + "\n");

       //开启后台任务执行
        HashMap<String, String> requestHeaders = getAllRequestHeaders();
        new M3u8DownloadWorker(m3u8Url,requestHeaders).execute();
        startButton.setEnabled(true);
    }





    private class M3u8DownloadWorker extends SwingWorker<Void, String> {

        private String m3u8Url;

        private HashMap<String, String> requestHeaders;
        public M3u8DownloadWorker(String m3u8Url, HashMap<String, String> requestHeaders) {
            this.m3u8Url = m3u8Url;
            this.requestHeaders = requestHeaders;
        }

        @Override
        protected Void doInBackground() {
            try {
                publish("解析m3u8文件...");
                java.util.List<String> tsUrls = parseM3U8(m3u8Url,requestHeaders);
                publish("共找到分片: " + tsUrls.size());
                File file = new File(saveM3u8Dir);
                if (file.exists() || !file.isDirectory()) {
                    file.mkdirs();
                }

                ExecutorService executor = Executors.newFixedThreadPool(8);
                int total = tsUrls.size();
                final int[] completed = {0};

                for (int i = 0; i < total; i++) {
                    int index = i;
                    executor.submit(() -> {
                        try {
                            String tsUrl = tsUrls.get(index);
                            String outputFile = String.format("%s/%05d.ts", saveM3u8Dir, index);
                            int retry = 0;
                            while (retry < 3) {
                                try {
                                    downloadFile(tsUrl, outputFile,requestHeaders);
                                    break;
                                } catch (IOException e) {
                                    retry++;
                                    publish("重试 " + retry + ": " + tsUrl);
                                }
                            }
                            synchronized (completed) {
                                completed[0]++;
                                int progress = (int) ((completed[0] * 100.0f) / total);
                                setProgress(progress);
                            }
                        } catch (Exception e) {
                            publish("下载失败: " + e.getMessage());
                        }
                    });
                }
                executor.shutdown();
                executor.awaitTermination(2, TimeUnit.HOURS);

                publish("分片下载完成，开始合并...");
                mergeTsFiles(total, "merged.ts");
                publish("合并完成，正在转换为MP4...");
                convertToMp4("merged.ts", "output.mp4");
                publish("下载完成，文件：output.mp4");

            } catch (Exception ex) {
                publish("出错：" + ex.getMessage());
            }
            return null;
        }

        @Override
        protected void process(List<String> chunks) {
            for (String msg : chunks) {
                logArea.append(msg + "\n");
            }
        }

        @Override
        protected void done() {
            startButton.setEnabled(true);
        }

        private void convertToMp4(String input, String output) throws IOException, InterruptedException {
            ProcessBuilder pb = new ProcessBuilder("ffmpeg", "-y", "-i", input, "-c", "copy", output);
            pb.redirectErrorStream(true);
            Process process = pb.start();
            try (BufferedReader br = new BufferedReader(new InputStreamReader(process.getInputStream()))) {
                String line;
                while ((line = br.readLine()) != null) {
                    publish(line);
                }
            }
            process.waitFor();
        }

        private void mergeTsFiles(int fileCount, String outputFile) throws IOException {
            try (FileOutputStream merged = new FileOutputStream(outputFile)) {
                for (int i = 0; i < fileCount; i++) {
                    String filePath = String.format("%s/%05d.ts", saveM3u8Dir, i);
                    Files.copy(Paths.get(filePath), merged);
                }
            }
        }

        private void downloadFile(String urlStr, String outputPath,Map<String,String> requestHeaders) throws IOException {

            try (InputStream in = HttpUtil.getUrlInputStream(urlStr,requestHeaders);
                 FileOutputStream out = new FileOutputStream(outputPath)) {
                byte[] buffer = new byte[8192];
                int len;
                while ((len = in.read(buffer)) != -1) {
                    out.write(buffer, 0, len);
                }
            }
        }

        private java.util.List<String> parseM3U8(String m3u8Url, Map<String,String> requestHeaders) throws IOException {
            String baseUrl = m3u8Url.substring(0, m3u8Url.lastIndexOf("/") + 1);

            BufferedReader reader = new BufferedReader(new InputStreamReader(HttpUtil.getUrlInputStream(m3u8Url,requestHeaders)));

            ArrayList<String> tsUrls = new ArrayList<>();
            String line;
            while ((line = reader.readLine()) != null) {
                line = line.trim();
                if (!line.isEmpty() && !line.startsWith("#")) {
                    if (line.startsWith("http")) {
                        tsUrls.add(line);
                    } else {
                        tsUrls.add(baseUrl + line);
                    }
                }
            }
            reader.close();
            return tsUrls;
        }

    }







}
